﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;

namespace GoodStuff.UnitTests
{
    [TestFixture]
    public class DateRangeTests
    {
        [Test]
        public void GetDuration()
        {
            DateTime now = DateTime.Now;

            DateRange range = new DateRange(now, now.AddDays(1));
            Assert.AreEqual(TimeSpan.FromDays(1), range.Duration);
        }

        [Test]
        public void ConstructFromTimeSpan()
        {
            DateTime now = DateTime.Now;
            
            DateRange range = new DateRange(now, TimeSpan.FromSeconds(20));
            Assert.AreEqual(range.End, now.AddSeconds(20));
        }

        [Test]
        public void TestOverlapRange()
        {
            DateTime now = DateTime.Now;

            DateRange range = new DateRange(now, TimeSpan.FromMinutes(5));
            DateRange range2 = new DateRange(now.AddSeconds(5), TimeSpan.FromMinutes(5));

            Assert.IsTrue(range.Overlaps(range2));
        }

        [Test]
        public void TestEquals()
        {
            DateTime now = DateTime.Now;

            DateRange range = new DateRange(now, TimeSpan.FromMinutes(5));
            DateRange range2 = new DateRange(now, TimeSpan.FromMinutes(5));

            Assert.IsTrue(range.Equals(range2));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void TestNegativeDurationEndDate()
        {
            DateTime now = DateTime.Now;

            DateRange range = new DateRange(now, TimeSpan.FromMinutes(-5));            
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void TestNegativeDuration()
        {
            DateTime now = DateTime.Now;

            DateRange range = new DateRange(now, now.AddSeconds(-2));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void TestNoDuration()
        {
            DateTime now = DateTime.Now;

            DateRange range = new DateRange(now, now);
        }

        [Test]
        public void TestClip()
        {
            DateTime now = DateTime.Now;

            DateRange range = new DateRange(now, now.AddHours(12));

            IDateRange newRange = range.Clip(new DateRange(now.AddHours(1), now.AddHours(24)));
            Assert.AreEqual(newRange.Start, now.AddHours(1));
            Assert.AreEqual(newRange.End, now.AddHours(12));
        }

        [Test]
        public void TestClipOutsideBounds()
        {
            DateTime now = DateTime.Now;

            DateRange range = new DateRange(now, now.AddHours(2));

            IDateRange newRange = range.Clip(new DateRange(now.AddHours(4), now.AddHours(12)));
            Assert.IsNull(newRange);
        }


        [Test]
        public void TestOverlapDate()
        {
            DateTime now = DateTime.Now;

            DateRange range = new DateRange(now, TimeSpan.FromMinutes(5));
            
            Assert.IsTrue(range.IsInRange(now.AddSeconds(5)));
        }

        [Test]
        public void TestBeforeNow()
        {
            DateTime now = DateTime.Now;

            DateRange range = new DateRange(now, TimeSpan.FromMinutes(5));

            Assert.IsFalse(range.IsInRange(now.AddSeconds(-5)));
        }

        [Test]
        public void TestTooLate()
        {
            DateTime now = DateTime.Now;

            DateRange range = new DateRange(now, TimeSpan.FromMinutes(5));

            Assert.IsFalse(range.IsInRange(now.AddMinutes(10)));
        }

        [Test]
        public void TestOverlapDateEdgeNow()
        {
            DateTime now = DateTime.Now;

            DateRange range = new DateRange(now, TimeSpan.FromMinutes(5));

            Assert.IsTrue(range.IsInRange(now));
        }

        [Test]
        public void TestOverlapDateEdgeEnd()
        {
            DateTime now = DateTime.Now;

            DateRange range = new DateRange(now, TimeSpan.FromMinutes(5));

            Assert.IsTrue(range.IsInRange(now.AddMinutes(5)));
        }

        [Test]
        public void Precedes()
        {
            DateTime now = DateTime.Now;

            DateRange range = new DateRange(now, TimeSpan.FromMinutes(5));

            Assert.IsTrue(now.AddDays(-1) < range);
            Assert.IsTrue(now.AddDays(-1) <= range);
            Assert.IsTrue(now <= range);
            Assert.IsFalse(now < range);            
        }

        [Test]
        public void Follows()
        {
            DateTime now = DateTime.Now;

            DateRange range = new DateRange(now, TimeSpan.FromMinutes(5));

            Assert.IsTrue(now.AddDays(2) > range);
            Assert.IsTrue(now.AddDays(2) >= range);
            Assert.IsTrue(now.AddMinutes(5) >= range);
            Assert.IsFalse(now.AddMinutes(5) > range);
        }
    }
}
